/**********************************************************

file:  atmega128_usart.c

Author:	  albert

 **********************************************************/

#include "atmega128_usart.h"
#include "Timer.h"


//volatile unsigned char data_received;

unsigned char usart_mode = 1; // For USART mode, 0 -> polling 1->Interrupt
unsigned char usart0_rec_buff[MAX_BUFFER_SIZE];
unsigned char usart1_rec_buff[MAX_BUFFER_SIZE];
volatile unsigned char usart0_count = 0;
volatile unsigned char usart1_count = 0;


/********************************************************
 *                                                       *
 * USART Initialization                                  *
 *                                                       *
 ********************************************************/

void USART_INIT(unsigned char usart_no, unsigned char usart_mode,unsigned int usart_speed)
{
  if (usart_mode == 0)
  {
    if (usart_no == 0)
    {
      UBRR0L = (((F_CPU / (usart_speed *16UL))) - 1);
      UBRR0H = ((((F_CPU / (usart_speed *16UL))) - 1) >> 8);
      UCSR0A = 0x00;
      //UMSEL0: 0 is asynchronous mode, 1 is synchronous mode
      UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); //8 bit data,1 stop bit,stop bit not apply to receiver
      UCSR0B = (1 << TXEN0) | (1 << RXEN0); // Turn on the transmission and reception circuitry
    }
    else
    {
      UBRR1L = (((F_CPU / (usart_speed *16UL))) - 1);
      UBRR1H = ((((F_CPU / (usart_speed *16UL))) - 1) >> 8);
      UCSR1A = 0x00;
      UCSR1C = (1 << UCSZ11) | (1 << UCSZ10); //8 bit data,1 stop bit,stop bit not apply to receiver
      UCSR1B = (1 << TXEN1) | (1 << RXEN1);
    }
  }
  else
  {
    if (usart_no == 0)
    {
      UBRR0L = (((F_CPU / (usart_speed *16UL))) - 1);
      UBRR0H = ((((F_CPU / (usart_speed *16UL))) - 1) >> 8);
      UCSR0A = 0x00;
      UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); //8 bit data,1 stop bit,stop bit not apply to receiver
      UCSR0B = (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0); //receiver interrupt enable
    }
    else
    {
      UBRR1L = (((F_CPU / (usart_speed *16UL))) - 1);
      UBRR1H = ((((F_CPU / (usart_speed *16UL))) - 1) >> 8);
      UCSR1A = 0x00;
      UCSR1C = (1 << UCSZ11) | (1 << UCSZ10); //8 bit data,1 stop bit,stop bit not apply to receiver
      UCSR1B = (1 << TXEN1) | (1 << RXEN1) | (1 << RXCIE1); //receiver interrupt enable
    }
  }
}

/********************************************************
 *                                                       *
 * Send byte(Polling)                                    *
 *                                                       *
 ********************************************************/

void USART_Transmit(unsigned char usart_no, unsigned char data)
{
  if (usart_no == 0)
  {
    while ((UCSR0A &(1 << UDRE0)) == 0)
      ;
    //waiting for transmit buffer to be available
    UDR0 = data;
  }
  else
  {
    while ((UCSR1A &(1 << UDRE1)) == 0)
      ;
    UDR1 = data;
  }

}

/********************************************************
 *                                                       *
 * Send string                                           *
 *                                                       *
 ********************************************************/

void USART_BYTES_Transmit(unsigned char usart_no, unsigned char data_array[], unsigned int size_of_array)
{

  for (unsigned int n = 0; n < size_of_array; n++)
  {
    if (usart_no == 0)
    {
      while ((UCSR0A &(1 << UDRE0)) == 0)
        ;
      UDR0 = data_array[n];
    }
    else
    {
      while ((UCSR1A &(1 << UDRE1)) == 0)
        ;
      UDR1 = data_array[n];
    }
  }
}

/**************************************************************************
 *                                                                        *
 **************************************************************************/

void Data_process(unsigned char usart_no, unsigned char data)
{
  if (usart_no == 0)
  {
    if (usart0_count < MAX_BUFFER_SIZE)
    {
      usart0_rec_buff[usart0_count] = data;
      usart0_count++;
    }
    //else exceed the buff size
  }
  else
  {

    if (usart1_count < MAX_BUFFER_SIZE)
    {
      usart1_rec_buff[usart1_count] = data;
      usart1_count++;
    }

  }

}

/********************************************************
 *                                                       *
 * Receive byte(Polling)                                 *
 *                                                       *
 ********************************************************/

void USART_Receive(unsigned char usart_no)
{
  unsigned char data;
  if (timer_enable == 1)
  {
    Timer1_TwoSecond();
    if (usart_no == 0)
    {
      while (!(UCSR0A &(1 << RXC0)) && timer_tick == 0)
        ;
      //waiting for data
      data = UDR0; //UDR0 can only be read once
      Data_process(0, data);
    }
    else
    {
      while (!(UCSR1A &(1 << RXC1)) && timer_tick == 0)
        ;
      data = UDR1;
      Data_process(1, data);

    }
  }
  else
  {
    if (usart_no == 0)
    {
      while (!(UCSR0A &(1 << RXC0)))
        ;
      //waiting for data
      data = UDR0; //UDR0 can only be read once
      Data_process(0, data);
    }
    else
    {
      while (!(UCSR1A &(1 << RXC1)))
        ;
      data = UDR1;
      Data_process(1, data);
    }
  }
}



/********************************************************
 *                                                       *
 * INTERRUPT                                             *
 * |better! NO function calls in the interrupt|          *
 ********************************************************/

ISR(USART0_RX_vect)
{
  usart0_rec_buff[usart0_count] = UDR0;
  usart0_count++;
}

/**************************************************************************
 *                                                                        *
 **************************************************************************/

ISR(USART1_RX_vect)
{
  usart1_rec_buff[usart1_count] = UDR1;
  usart1_count++;
}
